
/*************************************************
 * Description 	: -Collect a Byte stream and store it in a reception array
 * 				: -Then decode it to the desired instruction
 *				: -Initialize Timer0 on interupt basis
 * 				: -Then set the interrupt Timer0 and do the sekwence every  mSec
 * Last update 	: See File Date
 * Crystal 		:
 * Email 		:
 * 				: Decode_StateReception    ****************
 *				: 			Decode_WAITSTART (nothing to do waiting on start header )
 *				: 			Decode_STRTDEC (First character(adress recieved)
 *				: 			Decode_FLUSH (Reception is not ours, or character/recieved is garbage  )
 *				: 			Decode_DONE When this state is reached then an action can be executie in the instruction parser(or other logic )
 *				:
 *				: Functions **IN** 	********************
 *				: 	void Decode_AddB (*char) // Add a reception byte to the local instance
 *				:   void Decode_FlushInstr(void) // ReSet the instruction queue
 *				:	void Decode_Clone (*char ,*char) // Clones the current reception buffer to a new one
 *				: 	Decode_InstructionDecoder (unsigned char *Source) // executes the command that is currently in the instruction decoder
 *				: 	void Decode_initTimer0 (void) // interrupt T0 initializer
 *				:
 *				:
 *				: Functions **OUT** 	********************
 *				:
 *				:
 *				:
 *************************************************/

#include <avr/io.h>
#include <stdlib.h>
#include <stdint.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>


#include "Main.h"
#include "Decode.h"

volatile unsigned char  SekTmr_mSecExpired ; 	//Overflow Timer0 interrupt flag

static uint8_t Decode_m_uintStartBytesRec = 0 ; 	// Store here the counter off how many 0-bytes received
												// This is used to startup/init the state machine
static uint8_t Decode_m_uintFrameBytesRec = 0 ; 	// Store here the counter To accumulate the frames bytes
int16_t Decode_PWM =0 ;

Decode_State Decode_StateReception = Decode_WAITSTART ;
//Decode_State __attribute__((packed)) Decode_StateReception = Decode_WAITSTART;

void Decode_PWMInit (void)
{
	// TEST PWM as a Full inverted PWM at full clock speed
	// PWM11 & PWM10 are the PWM bit scale select = 10 bit
	// COM1A0 & COM1A1 Inverted PWM
	//TCCR1A = _BV(PWM11) | _BV(PWM10) | _BV(COM1A1) | _BV(COM1A0);	//Test PWM
	TCCR1A = _BV(WGM10) | _BV(WGM11) ;                     //8515_BV(PWM11) | _BV(PWM10) |  _BV(COM1A1);	//Test PWM
	TCCR1B = _BV(CS10);//Clock speed /8
	//LED_PORT_DIR = _BV(PD5); //SET OC1A as output (PIN5)


	TIMSK |= _BV(OCIE1A); // Enable output Compare
	LED_PORT_DIR |=_BV(PD5);

	Decode_PWM = 0x45 ;/// DEBUG
	OCR1A = Decode_PWM ;

}



SIGNAL(SIG_OUTPUT_COMPARE1A)
{

	OCR1A = (Decode_PWM);
	//LED_PORT  ^=_BV(4)	;// DEBUG
        //2010 07 23 Test svn 
}



void Decode_initTimer0 (void)

	{

          TCCR0 = _BV(CS02);// Set divider for CNT0 To Xtal /256
                  TCNT0 =Decode_TMR0_STRTCNT; // Load Start value for first interrupt (with precalculated value )
                  TIMSK |=_BV(TOIE0); // Set Interrupt flag
                  SekTmr_mSecExpired = 0x00; // Reset the (possible ) Int flag.
	}

SIGNAL(SIG_OVERFLOW0 )//'1 mSec Overflow interrupt occured
{

 	TCNT0 = Decode_TMR0_STRTCNT; // Load Start value for first interrupt
	SekTmr_mSecExpired = 0xFF; // Signal other code that one mSec is elapsed

}



void Decode_AddB ( int intTmp)
{
// master routine that counts the number off chars recieved
// and load an instruction string in a local variable


	LED_PORT  ^=_BV(5); // debug

      if (Decode_StateReception == Decode_WAITSTART )// is our receiver in IDLE decoding mode?
              {


                      if (intTmp == 0x00)// Test if the byte is a startbyte

                      {

                              if (Decode_m_uintStartBytesRec >= CNTNULLENGTH)
                              {
                                      // Extra null bytes are ignored
				              }
                              else
                              {
                                      // Upcount to complete start frame
                                      Decode_m_uintStartBytesRec++; // increment the Startbyte counter
				              }
                      }
                      else
                      {
                              // Adress Resolver

                              if ((intTmp == RECEIVERADDR) & (Decode_m_uintStartBytesRec >= CNTNULLENGTH))
                              {
                                      // ok the device adress is received so switch to decoding state
                                      Decode_StateReception = Decode_STRTDEC;
                                      Decode_Buff[Decode_RECADR] = intTmp ;//Load the adress from the reception character
                                      Decode_m_uintFrameBytesRec =0x01; //First Byte is recieved
                              }
                              else
                              {
                                      // this is not our address skip seq bytes
                                      //Decode_Buff[0] = 0x00;	// Reset the adress
                                      //Decode_m_uintFrameBytesRec =0x00; // Reset The Frame counter
                                      Decode_FlushInstr();
                              }
                              Decode_m_uintStartBytesRec=0; // Reset the Startbyte counter
                      }
              }
      else
      {

              if (Decode_StateReception == Decode_STRTDEC )
              {
                      // Add byte instruction until the complete frame is recieved
                      if (Decode_m_uintFrameBytesRec < FRAME_SIZE)
                      {	// add recieved byte to Buffer
                              Decode_Buff[Decode_m_uintFrameBytesRec] = intTmp;
                              if (Decode_m_uintFrameBytesRec < FRAME_SIZE-1)
                              {
                                      Decode_m_uintFrameBytesRec++;
                              }
                              else
                              {	// Last character is received so Signal This
                                      Decode_StateReception = Decode_DONE;
                              }

                      }
                      else
                      {
                              //Additional byte will be ignored..until flush is called
                      }
              }
			  else
			  {
			  }
      }
}

void Decode_FlushInstr ( void )
{
	// This function is called When
	// -start(ed) decoding frame not ours
	// -Error while decoding
	// -Set Decoder Ready for new packet

	Decode_Buff[Decode_RECADR] = 0x00;	// Reset the adress byte
	Decode_m_uintFrameBytesRec =0x00; // Reset The Frame counter
	Decode_m_uintStartBytesRec=0; // Reset the Startbyte counter
	Decode_StateReception = Decode_WAITSTART; // set Receiver ready


}

void Decode_Clone  (char *Source , char *Destination  )
{
	// This function is called to copy the current (best is ) complete instruction
	//to another char array
	unsigned char cntPosition ;

 	for ( cntPosition = 0; cntPosition < FRAME_SIZE; cntPosition++)
    {
		Destination[cntPosition ] = Source[cntPosition] ;
    }

}


void Decode_InstructionDecoder (unsigned char *Source)
// The instruction decoder does the actual thing that was send
// over the wire (serial)
// every action is best shorter then 1mSec and NEVER
// May exceed the receiving time of a frame !!!


{

	switch (Source[Decode_PHERADR])// For witch device this command is intended ?
	{
		//Source[Decode_PHERADR]=0x00; // Kill the instruction Pheriphal adress
		//LED_PORT  =Source[Decode_PHERADR];
	case Decode_PHER_SWITCH:			// This is a Switch on port A

		switch (Source[Decode_CMD1])
		{
		case Decode_CMD1_SETBYTE:// Command Switch on Port (All Bits in Value0)

			LED_PORT |= Source[Decode_VAL1];


			break;

		case Decode_CMD1_CLRBYTES:// Command Switch OFF Port (All Bits (=0) in Value0)

			LED_PORT &= Source[Decode_VAL1];

			break;

		default:return;

		}



	case Decode_PHER_DIMPWM:// This is a PWM Dimmer (For DC Operation)


		switch (Source[Decode_CMD1 ])
		{
		case Decode_CMD1_SETPWM:// Command Set Port on PWM duty Cycle
			// Make from Two bytes a integer (16 bits)
			Decode_PWM = ( Source[Decode_VAL1 ]<<8) + ( Source[Decode_VAL2 ]);

			break;

		case Decode_CMD1_CLRPWM:// Command Switch OFF Port (All Bits (=0) in Value0)
			Decode_PWM =0x00;

			break;

		default:return;
		}
  	case Decode_PHER_DEBUG:// This is a PWM Dimmer (For DC Operation)
		switch (Source[Decode_CMD1 ])
		{
		case Decode_CMD1_DEBUG: // execute a Debug Command
		  	LED_PORT &= 0xF0;
		  	LED_PORT |= ( Source[Decode_VAL1] && 0x0F);
			LED_PORT  ^=_BV(5);
			break;
		}


	default:
		break; //LED_PORT  ^=_BV(6); //error default condition


	}
}

